﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace VisualGTest
{
    /// <summary>
    /// Represents the result of running a test.
    /// </summary>
    public class TestResult : INotifyPropertyChanged
    {
        public enum TestStatus
        {
            Failure,
            Pending,
            Started,
            Success
        }

        public event PropertyChangedEventHandler PropertyChanged;

        #region property backing variables
        private string _testCaseName;
        private string _testName;
        private DateTime _startTime;
        private DateTime _endTime;
        private TestStatus _status;
        private TestFailureInfo _failureInfo;
        #endregion

        #region properties
        public string TestCaseName
        {
            get
            {
                return _testCaseName;
            }
            set
            {
                if (_testCaseName != value)
                {
                    _testCaseName = value;
                    NotifyPropertyChanged("TestCaseName");
                }
            }
        }

        public string TestName
        {
            get
            {
                return _testName;
            }
            set
            {
                if (_testName != value)
                {
                    _testName = value;
                    NotifyPropertyChanged("TestName");
                }
            }
        }

        /// <summary>
        /// The difference between StartTime and EndTime. Initially negative.
        /// </summary>
        public TimeSpan Duration
        {
            get { return EndTime - StartTime; }
        }

        public DateTime StartTime
        {
            get
            {
                return _startTime;
            }
            set
            {
                if (_startTime != value)
                {
                    _startTime = value;
                    NotifyPropertyChanged("StartTime");
                }
            }
        }

        public DateTime EndTime
        {
            get
            {
                return _endTime;
            }
            set
            {
                if (_endTime != value)
                {
                    _endTime = value;
                    NotifyPropertyChanged("EndTime");
                }
            }
        }

        public TestStatus Status
        {
            get
            {
                return _status;
            }
            set
            {
                if (_status != value)
                {
                    _status = value;
                    NotifyPropertyChanged("Status");
                }
            }
        }

        public TestFailureInfo FailureInfo
        {
            get { return _failureInfo; }
        }

        public bool Passed
        {
            get { return this.Status == TestStatus.Success; }
        }
        #endregion

        public TestResult(string testCaseName, string testName)
        {
            this.TestCaseName = testCaseName;
            this.TestName = testName;
            this.StartTime = DateTime.MaxValue;
            this.EndTime = DateTime.MinValue;
            this.Status = TestStatus.Pending;

            _failureInfo = new TestFailureInfo();

            this.FailureInfo.PropertyChanged += FailureInfo_PropertyChanged;
        }

        /// <summary>
        /// Copy constructor.
        /// </summary>
        /// <param name="other"></param>
        public TestResult(TestResult other)
        {
            this.TestCaseName = other.TestCaseName;
            this.TestName = other.TestName;
            this.StartTime = other.StartTime;
            this.EndTime = other.EndTime;
            this.Status = other.Status;

            _failureInfo = new TestFailureInfo(other.FailureInfo);

            this.FailureInfo.PropertyChanged += FailureInfo_PropertyChanged;
        }

        private void FailureInfo_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            NotifyPropertyChanged("FailureInfo");
        }

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }
}
